
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"

#define SRC_LED1_OFF GPIO_SetBits  (GPIOC,GPIO_Pin_13);
#define SRC_LED1_ON  GPIO_ResetBits(GPIOC,GPIO_Pin_13);

#define DP_Common_Left GPIO_Pin_7
#define DP_Common_Right GPIO_Pin_8

/*
宏定义，数码管a-g各段对应的比特，更换硬件只用改动以下8行
*/
#define    a 0x04   //  AAAA
#define    b 0x80   // F    B
#define    c 0x40   // F    B
#define    d 0x10   //  GGGG
#define    e 0x20   // E    C
#define    f 0x08   // E    C
#define    g 0x01   //  DDDD    H
#define    h 0x02


/*
自动生成段码表
*/
unsigned char LED_digit_table[] =
{
    a + b + c + d + e + f,  //"0"
    b + c,                  //"1"
    a + b + d + e + g,      //"2"
    a + b + c + d + g,      //"3"
    b + c + f + g,          //"4"
    a + c + d + f + g,      //"5"
    a + c + d + e + f + g,  //"6"
    a + b + c,              //"7"
    a + b + c + d + e + f + g, //"8"
    a + b + c + d + f + g,  //"9"
    b + c + e + f + g,      //"H"
    a + f + e + g,          //"C"
    d + e + f,              //"L"
    g,                      //"-"
    0x00                    //black
};

#undef a
#undef b
#undef c
#undef d
#undef e
#undef f
#undef g

void DisplayLeft(u8 num)
{
    GPIO_WriteBit(GPIOB, DP_Common_Left, Bit_RESET);
    GPIO_Write(GPIOA, LED_digit_table[num]);
    Delay_Ms(1);
    GPIO_WriteBit(GPIOB, DP_Common_Left, Bit_SET);
}

void DisplayRight(u8 num)
{
    GPIO_WriteBit(GPIOB, DP_Common_Right, Bit_RESET);
    GPIO_Write(GPIOA, LED_digit_table[num]);
    Delay_Ms(1);
    GPIO_WriteBit(GPIOB, DP_Common_Right, Bit_SET);
}

void DisplayNumber(u8 num, int32_t time)
{
    u8 j;
    for (j = 0; j < time; j++)
    {
        u8 i;
        if (num >= 10)
        {
            DisplayLeft(num / 10);
            i = num - (num / 10) * 10;
        }
        else
        {
            DisplayLeft(0);
            i = num;
        }
        DisplayRight(i);
    }
}

/**
动态显示驱动：数码管动态显示接口是单片机中应用最为广泛的一种显示方式之一，动态驱动是将所有
数码管的8个显示笔划"a,b,c,d,e,f,g,dp"的同名端连在一起，另外为每个数码管的公共极COM增加位选
通控制电路，位选通由各自独立的I/O线控制，当单片机输出字形码时，所有数码管都接收到相同的字
形码，但究竟是那个数码管会显示出字形，取决于单片机对位选通COM端电路的控制，所以我们只要将
需要显示的数码管的选通控制打开，该位就显示出字形，没有选通的数码管就不会亮。通过分时轮流控
制各个数码管的的COM端，就使各个数码管轮流受控显示，这就是动态驱动。在轮流显示过程中，每位
数码管的点亮时间为1～2ms，由于人的视觉暂留现象及发光二极管的余辉效应，尽管实际上各位数码管
并非同时点亮，但只要扫描的速度足够快，给人的印象就是一组稳定的显示数据，不会有闪烁感，动态
显示的效果和静态显示是一样的，能够节省大量的I/O端口，而且功耗更低。 
*/
int main(void)
{
    u8 i, j;
    GPIO_InitTypeDef def;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    Delay_Init();

    def.GPIO_Pin = GPIO_Pin_13;
    def.GPIO_Mode = GPIO_Mode_Out_PP;
    def.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &def);

    def.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8;
    def.GPIO_Mode = GPIO_Mode_Out_PP;
    def.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &def);

    def.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    def.GPIO_Mode = GPIO_Mode_Out_PP;	//推挽输出
    def.GPIO_Speed = GPIO_Speed_50MHz;	//IO口速度为50MHz
    GPIO_Init(GPIOA, &def);

    for(i = 0; i < 5; i++)
    {
        SRC_LED1_ON;
        Delay_Ms(60);
        SRC_LED1_OFF;
        Delay_Ms(60);
    }

    //Infinite loop
    while (1)
    {
        for (i = 0; i <= 99; i++)
        {
            DisplayNumber(i, 100);
        }
    }
}


#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
    /* User can add his own implementation to report the file name and line number,
       ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

    /* Infinite loop */
    while (1)
    {
    }
}
#endif
